Restful风格的Retrofit2网络请求器
简介
Retrofit2 以其简易的接口配置、强大的扩展支持、优雅的代码结构受到大家的追捧。Retrofit2 的 API 接口定义极具 Restful 风格,且很好的与okhttp3相互结合形成一个高效简洁的网络请求库。
1 | //通过接口定义你的api |
1 | //再由Retrofit生成 `GitHubService`接口相对应的方法 |
1 | //通过GitHubService生成的方法进行网络请求 |
详情请见Retrofit2官方教程
原理
Retrofit2库源码中最让人眼前一亮的设计是通过java的动态代理将接口中的每个方法和注解转化成一个单独的ServiceMethod
,之后在ServiceMethod
中查找合适的CallAdapterFactory
和ConverterFactory
对数据进行处理。
- Java的注解和动态代理原理
- CallAdapter及其Factory设计思路
- Converter及其Factory设计思路
以上亦是整个库的核心原理。
解析
预先准备
1 | Retrofit retrofit = new Retrofit.Builder() |
整个流程由Retrofit
的build开始,将一些必须的参数如baseUrl
,CallAdapterFactory
,ConverterFactory
传入到Retrofit
中,之后通过create方法对接口文件中的方法建立动态代理,使得每当方法被调用时都能走到代理的方法中。
1 | public <T> T create(final Class<T> service) { |
调用
上面已经说过,当service中的方法被调用时会走入之前的动态代理方法中,那看看该代理方法中做了哪些事情。
首先通过 ServiceMethodCache
查看是否有该方法的缓存,如果没有则通过ServiceMethod的Builder传入retrofit构建出来。
在 ServiceMethod
的builder构建方法中
1 | public ServiceMethod build() { |
CallAdapterFactory和CallAdapter
再说CallAddapterFactory
前,先说说这个是干什么用的。简而言之就是将Retrofit原生默认的call这个请求对象转换成开发者想要的对象,比如说RxJava中Observable之类。
在动态代理方法中,可以看到有这么一行代码,这里的OkHttpCall
是对于OkHttp的一个封装,也就是说我们通过Retrofit进行网络请求实质就是通过OkHttp来进行请求。1
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
随之其后的是 callAdapter的adapt方法1
return serviceMethod.callAdapter.adapt(okHttpCall);
serviceMethod 中的 callAdapter 则是在 Retrofit 的 adapterFactories 中查找而得(之前在Retrofit的构建过程中添加addCallAdapterFactory()
)1
2
3
4
5
6
7int start = adapterFactories.indexOf(skipPast) + 1;
for (int i = start, count = adapterFactories.size(); i < count; i++) {
CallAdapter<?, ?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
}
查找规则则是通过在 CallAdapterFactory
的get方法中判断returnType来进行,一旦查找成功后就会返回相应的CallAdapter。
比如说在 Retrofit2 自带的
DefaultCallAdapterFactory
则是判断getRawType(returnType) == Call.class
,若是则返回原生的Call在
Rxjava2CallAdapterFactory
中是判断 returnType 是否等于Completable
、Flowable
、Single
、Maybe
或者Observable
,是则返回Rxjava2CallAdapter
.
最后在 CallAdapter 的 adapter方法中可以将传入的call对象转换成自己想要的对象。
ConverterFactory和Converter
Converter 是负责对请求数据和返回数据进行转换的功能,设计思路与 CallAdapterFactory 相似。在 ConverterFactory中有两个比较重要的方法,一个是 requestBodyConverter
,这个方法也是通过判断传入的 Type 类型来决定对请求数据的 RequestBodyConverter
器,要求返回Converter<?, RequestBody>
类型。
另一个是responseBodyConverter
,要求返回Converter<ResponseBody, ?>
类型。
RequestBodyConverter
一般会在 @Body
,@Part
以及@PartMap
的参数解析中使用,用来将请求的数据转换到标准的RequestBody格式。
比如说在
@Part
注解下的参数解析中,由于参数的类型为RequestBody,则ConverterFactory 会优先返回Retrofit自带的BuiltInConverters
中的RequestBodyConverter
,负责转换RequestBody。而在
@Body
注解下的参数解析中,则有可能会进入GsonConverterFactory
的GsonRequestBodyConverter
中,负责将@Body
声明的实体转换成json字符创。
1 | // BuiltInConverters下的requestBodyConverter方法 |
ResponseBodyConverter
则是在 okHttpCall 访问网络结束后调用1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 // OkHttpCall类中的方法
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
//...省略部分代码
try {
T body = serviceMethod.toResponse(catchingBody);
return Response.success(body, rawResponse);
} catch (RuntimeException e) {
// If the underlying source threw an exception, propagate that rather than indicating it was
// a runtime exception.
catchingBody.throwIfCaught();
throw e;
}
}
// ServiceMethod类中的方法
/** Builds a method return value from an HTTP response body. */
R toResponse(ResponseBody body) throws IOException {
return responseConverter.convert(body);
}
其中 serviceMethod.toResponse()
即会调用之前通过ConverterFactory
得到的responseConverter.convert
方法,将ResponseBody转化为自己想要的数据类型。
这里要注意一点,在之前说过的CallAdapter中有一个responseType()
方法,此方法返回的数据类型要与responseConverter.convert(body)
的返回类型保持一致。
结语
Retrofit 本身是通过 OkHttp3 实现的网络请求,首先通过动态代理的方式为api service 中的每一个方法一一对应的生成了ServiceMethod;同时通过提供自定义CallAdapterFactory
的方式能够将默认的Call请求方法转换成开发者自己想要的数据对象;不知如此,还通过自定义ConverterFactory
的方式能够自由的进行请求数据与RequestBody,ResponseBody与返回数据的数据转换。
通过以上所介绍,Retrofit2比较重要的几个原理部分都进行了简单说明。
Retrofit2实现了自身强大的功能与扩展性,能够方便的实现开发者自己想要的功能,同时其美丽而又简洁的代码也是我们借鉴的一个目标。
参考资料: